home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / lib / libpq / portal.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  13.6 KB  |  584 lines

  1. /* ----------------------------------------------------------------
  2.  *   FILE
  3.  *    portal.c
  4.  *    
  5.  *   DESCRIPTION
  6.  *    generalized portal support routines
  7.  *
  8.  *   UTILITY ROUTINES
  9.  *    pqdebug        - send a string to the debugging output port
  10.  *    pqdebug2    - send two strings to stdout
  11.  *    PQtrace        - turn on pqdebug() tracing
  12.  *    PQuntrace    - turn off pqdebug() tracing
  13.  *
  14.  *   INTERFACE ROUTINES
  15.  *    PQnportals     - Return the number of open portals. 
  16.  *    PQpnames     - Return all the portal names
  17.  *    PQparray     - Return the portal buffer given a portal name
  18.  *    PQrulep     - Return 1 if an asynchronized portal
  19.  *    PQntuples     - Return the number of tuples in a portal buffer
  20.  *    PQninstances    -   same as PQntuples using object terminology
  21.  *    PQngroups     - Return the number of tuple groups in a portal buffer
  22.  *    PQntuplesGroup     - Return the number of tuples in a tuple group
  23.  *    PQninstancesGroup  - same as PQntuplesGroup using object terminology
  24.  *    PQnfieldsGroup     - Return the number of fields in a tuple group
  25.  *    PQfnumberGroup     - Return field number given (group index, field name)
  26.  *    PQfnameGroup     - Return field name given (group index, field index)
  27.  *    PQgroup     - Return the tuple group that a particular tuple is in
  28.  *    PQgetgroup     - Return the index of the group that a tuple is in
  29.  *    PQnfields     - Return the number of fields in a tuple
  30.  *    PQfnumber     - Return the field index of a field name in a tuple
  31.  *    PQfname     - Return the name of a field
  32.  *    PQftype     - Return the type of a field
  33.  *    PQsametype     - Return 1 if the two tuples have the same type
  34.  *    PQgetvalue     - Return an attribute (field) value
  35.  *    PQgetlength     - Return an attribute (field) length
  36.  *    PQclear        - free storage claimed by named portal
  37.  *      PQnotifies      - Return a list of relations on which notification 
  38.  *                        has occurred.
  39.  *      PQremoveNotify  - Remove this notification from the list.
  40.  *
  41.  *   NOTES
  42.  *    These functions may be used by both frontend routines which
  43.  *    communicate with a backend or by user-defined functions which
  44.  *    are compiled or dynamically loaded into a backend.
  45.  *
  46.  *    the portals[] array should be organized as a hash table for
  47.  *    quick portal-by-name lookup.
  48.  *
  49.  *    Do not confuse "PortalEntry" (or "PortalBuffer") with "Portal"
  50.  *    see utils/mmgr/portalmem.c for why. -cim 2/22/91
  51.  *
  52.  *   IDENTIFICATION
  53.  *    $Header: /private/postgres/src/lib/libpq/RCS/portal.c,v 1.16 1992/07/15 05:09:13 mao Exp $
  54.  * ----------------------------------------------------------------
  55.  */
  56.  
  57. #include <string.h>
  58.  
  59. #include "tmp/c.h"
  60. #include "tmp/simplelists.h"
  61. #include "tmp/libpq.h"
  62. #include "utils/exc.h"
  63.  
  64. RcsId("$Header: /private/postgres/src/lib/libpq/RCS/portal.c,v 1.16 1992/07/15 05:09:13 mao Exp $");
  65.  
  66. /* ----------------
  67.  *    exceptions
  68.  * ----------------
  69.  */
  70. Exception MemoryError = {"Memory Allocation Error"};
  71. Exception PortalError = {"Invalid arguments to portal functions"};
  72. Exception PostquelError = {"Postquel Error"};
  73. Exception ProtocolError = {"Protocol Error"};
  74. char PQerrormsg[error_msg_length];
  75.  
  76. int    PQtracep = 0;        /* 1 to print out debugging message */
  77. FILE    *debug_port = (FILE *)NULL;
  78.  
  79. /* ----------------------------------------------------------------
  80.  *            PQ utility routines
  81.  * ----------------------------------------------------------------
  82.  */
  83. void
  84. pqdebug (target, msg)
  85. char *target, *msg;
  86. {
  87.     if (PQtracep) {
  88.     /*
  89.      * if nothing else was suggested default to stdout
  90.      */
  91.     if (!debug_port)
  92.         debug_port = stdout;
  93.     fprintf(debug_port, target, msg);
  94.     fprintf(debug_port, "\n");
  95.     }
  96. }
  97.  
  98. void
  99. pqdebug2(target, msg1, msg2)
  100. char *target, *msg1, *msg2;
  101. {
  102.     if (PQtracep) {
  103.     printf(target, msg1, msg2);
  104.     printf("\n");
  105.     }
  106. }
  107.  
  108. /* --------------------------------
  109.  *    PQtrace() / PQuntrace()
  110.  * --------------------------------
  111.  */
  112. void
  113. PQtrace()
  114. {
  115.     PQtracep = 1;
  116. }
  117.  
  118. void
  119. PQuntrace()
  120. {
  121.     PQtracep = 0;
  122. }
  123.  
  124. /* ----------------------------------------------------------------
  125.  *            PQ portal interface routines
  126.  * ----------------------------------------------------------------
  127.  */
  128.  
  129. /* --------------------------------
  130.  *    PQnportals - Return the number of open portals. 
  131.  *     If rule_p, only return asynchronized portals. 
  132.  * --------------------------------
  133.  */
  134. int
  135. PQnportals(rule_p)
  136.     int rule_p;
  137. {
  138.     int i, n = 0;
  139.     
  140.     for (i = 0; i < MAXPORTALS; i++) 
  141.     if (portals[i] != NULL)
  142.         if (!rule_p || portals[i]->portal->rule_p)
  143.         n++;
  144.     
  145.     return n;
  146. }
  147.  
  148. /* --------------------------------
  149.  *    PQpnames - Return all the portal names
  150.  *     If rule_p, only return asynchronized portals. 
  151.  * --------------------------------
  152.  */
  153. void
  154. PQpnames(pnames, rule_p)
  155.      char *pnames[MAXPORTALS];
  156.      int rule_p;
  157. {
  158.     int i;
  159.  
  160.     for (i = 0; i < MAXPORTALS; i++)
  161.     if (portals[i] != NULL) {
  162.         if (!rule_p || portals[i]->portal->rule_p) 
  163.         strcpy(pnames[i], portals[i]->name);
  164.         else pnames[i] = NULL;
  165.     }
  166.     else 
  167.         pnames[i] = NULL;
  168. }
  169.  
  170. /* --------------------------------
  171.  *    PQparray - Return the portal buffer given a portal name
  172.  * --------------------------------
  173.  */
  174. PortalBuffer *
  175. PQparray(pname)
  176.     char *pname;
  177. {
  178.     int i;
  179.     
  180.     if ((i = pbuf_getIndex(pname)) == -1) 
  181.     return (PortalBuffer *) NULL;
  182.     
  183.     return (portals[i]->portal);
  184. }
  185.  
  186. /* --------------------------------
  187.  *    PQrulep - Return 1 if an asynchronized portal
  188.  * --------------------------------
  189.  */
  190. int
  191. PQrulep(portal)
  192.     PortalBuffer *portal;
  193. {
  194.     return (portal->rule_p);
  195. }
  196.  
  197. /* --------------------------------
  198.  *    PQntuples - Return the number of tuples in a portal buffer
  199.  * --------------------------------
  200.  */
  201. int
  202. PQntuples(portal)
  203.     PortalBuffer *portal;
  204. {
  205.     return (portal->no_tuples);
  206. }
  207.  
  208. int
  209. PQninstances(portal)
  210.     PortalBuffer *portal;
  211. {
  212.     return PQntuples(portal);
  213. }
  214.  
  215. /* --------------------------------
  216.  *    PQngroups - Return the number of tuple groups in a portal buffer
  217.  * --------------------------------
  218.  */
  219. int
  220. PQngroups(portal)
  221.     PortalBuffer *portal;
  222. {
  223.     return (portal->no_groups);
  224. }
  225.  
  226.  
  227. /* --------------------------------
  228.  *    PQntuplesGroup - Return the number of tuples in a tuple group
  229.  * --------------------------------
  230.  */
  231. int
  232. PQntuplesGroup(portal, group_index)
  233.     PortalBuffer *portal;
  234.     int      group_index;
  235. {
  236.     return
  237.     pbuf_findGroup(portal, group_index)->no_tuples;
  238. }
  239.  
  240. int
  241. PQninstancesGroup(portal, group_index)
  242.     PortalBuffer *portal;
  243.     int      group_index;
  244. {
  245.     return
  246.     PQntuplesGroup(portal, group_index);
  247. }
  248.  
  249. /* --------------------------------
  250.  *    PQnfieldsGroup - Return the number of fields in a tuple group
  251.  * --------------------------------
  252.  */
  253. int
  254. PQnfieldsGroup(portal, group_index)
  255.     PortalBuffer *portal;
  256.     int         group_index;
  257. {
  258.     return
  259.     pbuf_findGroup(portal, group_index)->no_fields;
  260. }
  261.  
  262. /* --------------------------------
  263.  *    PQfnumberGroup - Return the field number (index) given
  264.  *             the group index and the field name
  265.  * --------------------------------
  266.  */
  267. int
  268. PQfnumberGroup(portal, group_index, field_name)
  269.     PortalBuffer *portal;
  270.     int         group_index;
  271.     char     *field_name;
  272. {
  273.     return
  274.     pbuf_findFnumber( pbuf_findGroup(portal, group_index), field_name);
  275. }
  276.  
  277. /* --------------------------------
  278.  *    PQfnameGroup - Return the field (attribute) name given
  279.  *            the group index and field index. 
  280.  * --------------------------------
  281.  */
  282. char *
  283. PQfnameGroup(portal, group_index, field_number)
  284.     PortalBuffer *portal;
  285.     int group_index;
  286.     int field_number;
  287. {
  288.     return
  289.     pbuf_findFname( pbuf_findGroup(portal, group_index), field_number);
  290. }
  291.  
  292. /* --------------------------------
  293.  *    PQgroup - Return the tuple group that a particular tuple is in
  294.  * --------------------------------
  295.  */
  296. GroupBuffer *
  297. PQgroup(portal, tuple_index)
  298.     PortalBuffer *portal;
  299.     int         tuple_index;
  300. {
  301.     GroupBuffer *group;
  302.  
  303.     if (tuple_index < 0 || tuple_index >= portal->no_tuples)
  304.     libpq_raise(&PortalError, 
  305.              form((int)"tuple index %d out of bound.", tuple_index));
  306.     
  307.     group = portal->groups;
  308.  
  309.     while (tuple_index >= group->no_tuples) {
  310.     tuple_index -= group->no_tuples;
  311.     group = group->next;
  312.     }
  313.  
  314.     return (group);
  315. }
  316.  
  317. /* --------------------------------
  318.  *    PQgetgroup - Return the index of the group that a
  319.  *             partibular tuple is in
  320.  * --------------------------------
  321.  */
  322. int
  323. PQgetgroup(portal, tuple_index)
  324.     PortalBuffer *portal;
  325.     int         tuple_index;
  326. {
  327.     GroupBuffer *group;
  328.     int n = 0;
  329.  
  330.     if (tuple_index < 0 || tuple_index >= portal->no_tuples)
  331.     libpq_raise(&PortalError, 
  332.              form((int)"tuple index %d out of bound.", tuple_index));
  333.     
  334.     group = portal->groups;
  335.  
  336.     while (tuple_index >= group->no_tuples) {
  337.     n++;
  338.     tuple_index -= group->no_tuples;
  339.     group = group->next;
  340.     }
  341.  
  342.     return (n);
  343. }
  344.  
  345. /* --------------------------------
  346.  *    PQnfields - Return the number of fields in a tuple
  347.  * --------------------------------
  348.  */
  349. int
  350. PQnfields(portal, tuple_index)
  351.     PortalBuffer *portal;
  352.     int         tuple_index;
  353. {
  354.     return
  355.     PQgroup(portal, tuple_index)->no_fields;
  356. }
  357.  
  358. /* --------------------------------
  359.  *    PQfnumber - Return the field index of a given
  360.  *            field name within a tuple. 
  361.  * --------------------------------
  362.  */
  363. int
  364. PQfnumber(portal, tuple_index, field_name)
  365.     PortalBuffer *portal;
  366.     int         tuple_index;
  367.     char     *field_name;
  368. {
  369.     return
  370.     pbuf_findFnumber( PQgroup(portal, tuple_index), field_name);
  371. }
  372.  
  373. /* --------------------------------
  374.  *    PQfname - Return the name of a field
  375.  * --------------------------------
  376.  */
  377. char *
  378. PQfname(portal, tuple_index, field_number)
  379.     PortalBuffer *portal;
  380.     int         tuple_index;
  381.     int         field_number;
  382. {
  383.     return
  384.     pbuf_findFname( PQgroup(portal, tuple_index), field_number);
  385. }
  386.  
  387. /* --------------------------------
  388.  *    PQftype - Return the type of a field
  389.  * --------------------------------
  390.  */
  391. int 
  392. PQftype(portal, tuple_index, field_number)
  393.     PortalBuffer *portal;
  394.     int         tuple_index;
  395.     int         field_number;
  396. {
  397.     GroupBuffer *group;
  398.     
  399.     group = PQgroup(portal, tuple_index);
  400.     pbuf_checkFnumber(group, field_number);
  401.     
  402.     return
  403.     (group->types + field_number)->adtid;
  404. }
  405.  
  406. /* --------------------------------
  407.  *    PQsametype - Return 1 if the two tuples have the same type
  408.  *            (in the same group)
  409.  * --------------------------------
  410.  */
  411. int
  412. PQsametype(portal, tuple_index1, tuple_index2)
  413.     PortalBuffer *portal;
  414.     int         tuple_index1;
  415.     int         tuple_index2;
  416. {
  417.     return
  418.     (PQgroup(portal, tuple_index1) == PQgroup(portal, tuple_index2));
  419. }
  420.  
  421. /* --------------------------------
  422.  *    PQgetvalue - Return an attribute (field) value
  423.  * --------------------------------
  424.  */
  425. char *
  426. PQgetvalue(portal, tuple_index, field_number)
  427.     PortalBuffer *portal;
  428.     int         tuple_index;
  429.     int         field_number;
  430. {
  431.     GroupBuffer *group;
  432.     TupleBlock  *tuple_ptr;
  433.  
  434.     if (tuple_index < 0 || tuple_index >= portal->no_tuples)
  435.     libpq_raise(&PortalError, 
  436.             form((int)"tuple index %d out of bound.", tuple_index));
  437.     
  438.     group = portal->groups;
  439.  
  440.     while (tuple_index >= group->no_tuples) {
  441.     tuple_index -= group->no_tuples;
  442.     group = group->next;
  443.     }
  444.     
  445.     tuple_ptr = group->tuples;    
  446.  
  447.     while (tuple_index >= TupleBlockSize) {
  448.     tuple_index -= TupleBlockSize;
  449.     tuple_ptr = tuple_ptr->next;
  450.     }
  451.  
  452.     pbuf_checkFnumber(group, field_number);
  453.     
  454.     return
  455.     tuple_ptr->values[tuple_index][field_number];
  456. }
  457.  
  458. /* --------------------------------
  459.  *    PQgetlength - Return an attribute (field) length
  460.  * --------------------------------
  461.  */
  462. int
  463. PQgetlength(portal, tuple_index, field_number)
  464.     PortalBuffer *portal;
  465.     int         tuple_index;
  466.     int         field_number;
  467. {
  468.     GroupBuffer *group;
  469.     TupleBlock  *tuple_ptr;
  470.  
  471.     if (tuple_index < 0 || tuple_index >= portal->no_tuples)
  472.     libpq_raise(&PortalError, 
  473.             form((int)"tuple index %d out of bound.", tuple_index));
  474.     
  475.     group = portal->groups;
  476.  
  477.     while (tuple_index >= group->no_tuples) {
  478.     tuple_index -= group->no_tuples;
  479.     group = group->next;
  480.     }
  481.     
  482.     tuple_ptr = group->tuples;    
  483.  
  484.     while (tuple_index >= TupleBlockSize) {
  485.     tuple_index -= TupleBlockSize;
  486.     tuple_ptr = tuple_ptr->next;
  487.     }
  488.  
  489.     pbuf_checkFnumber(group, field_number);
  490.     
  491.     return
  492.     tuple_ptr->lengths[tuple_index][field_number];
  493. }
  494.  
  495. /* ----------------
  496.  *    PQclear        - free storage claimed by named portal
  497.  * ----------------
  498.  */
  499. void
  500. PQclear(pname)
  501.     char *pname;
  502. {    
  503.     pbuf_close(pname);
  504. }
  505.  
  506. /*
  507.  * async notification.
  508.  * This is going away with pending rewrite of comm. code...
  509.  */
  510.  
  511. SLList pqNotifyList;
  512. static int initialized = 0;    /* statics in this module initialized? */
  513.  
  514. /* remove invalid notifies before returning */
  515. void
  516. PQcleanNotify()
  517. {
  518.     PQNotifyList *last = NULL;
  519.     PQNotifyList *nPtr;
  520.     for (nPtr = (PQNotifyList *)SLGetHead(&pqNotifyList);
  521.      nPtr != NULL;
  522.      nPtr = (PQNotifyList *)SLGetSucc(&nPtr->Node)) {
  523.     if (last != NULL && last->valid == 0) {
  524.         SLRemove(&last->Node);
  525.         pbuf_free((caddr_t)last);
  526.     }
  527.     last = nPtr;
  528.     }
  529.     if (last != NULL && last->valid == 0) {
  530.     SLRemove(&last->Node);
  531.     pbuf_free((caddr_t)last);
  532.     }
  533. }
  534.  
  535.  
  536. void
  537. PQnotifies_init() {
  538.     PQNotifyList *nPtr;
  539.  
  540.     if (! initialized) {
  541.     initialized = 1;
  542.     SLNewList(&pqNotifyList,offsetof(PQNotifyList,Node));
  543.     } else {            /* clean all notifies */
  544.     for (nPtr = (PQNotifyList *)SLGetHead(&pqNotifyList) ;
  545.          nPtr != NULL;
  546.          nPtr = (PQNotifyList *)SLGetSucc(&nPtr->Node)) {
  547.         nPtr->valid = 0;
  548.     }
  549.     PQcleanNotify();
  550.     }
  551. }
  552.  
  553. PQNotifyList *
  554. PQnotifies()
  555. {
  556.     PQcleanNotify();
  557.     return (PQNotifyList *)SLGetHead(&pqNotifyList);
  558. }
  559.  
  560. void
  561. PQremoveNotify(nPtr)
  562.      PQNotifyList *nPtr;
  563. {
  564.     nPtr->valid = 0;        /* remove later */
  565. }
  566.  
  567. void 
  568. PQappendNotify(relname,pid)
  569.      char *relname;
  570.      int pid;
  571. {
  572.     PQNotifyList *nPtr;
  573.     if (! initialized) {
  574.     initialized = 1;
  575.     SLNewList(&pqNotifyList,offsetof(PQNotifyList,Node));
  576.     }
  577.     nPtr = (PQNotifyList *)pbuf_alloc(sizeof(PQNotifyList));
  578.     strcpy(nPtr->relname,relname);
  579.     nPtr->be_pid = pid;
  580.     nPtr->valid = 1;
  581.     SLNewNode(&nPtr->Node);
  582.     SLAddTail(&pqNotifyList,&nPtr->Node);
  583. }
  584.